package task

import (
	"errors"
	"fmt"
	"oa-rest/common"
	"path/filepath"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
)

/*
	  发起一个任务，需要做以下逻辑判定：
		1.根据任务类型
		2.
*/
func newTaskHandler(c *gin.Context) {
	var req Task
	var res common.Response

	if err := c.ShouldBindJSON(&req); err != nil {
		res.Format(c, err.Error())
		return
	}
	if req.Type == 0 || req.SubType == 0 || req.EndTime == "" || req.Title == "" || req.Content == "" || len(req.NodeList) == 0 {
		res.Format(c, "params error")
		return
	}

	// todo 后续看这里是否需要合并
	var err error
	switch req.Type {
	case 1: // 公文
		err = req.SavTask(c)
	case 2: // 提案
		err = req.SavTask(c)
	case 3: // 请假
		err = errors.New("该类型还不支持！")
	default:
		err = errors.New("该类型还不支持！")
	}
	if err != nil {
		res.Format(c, err.Error())
		return
	}
	res.Data = req.Id

	res.Format(c)
}

/*
	任务的每个节点审核时，都要判定是否是最后一个节点，然后任务结束，归档
	1.根据任务类型，进行不同的操作
	2.根据审批结果，进行不同处理（批准，进入下一级；驳回，返回上一级）
	3.根据批注结果，只更新对应信息
*/

type approveParam struct {
	TaskId  int64           `json:"taskId"`
	NodeId  int64           `json:"nodeId"`
	Flag    int64           `json:"flag"`    // 1.通过；2.驳回；3.批注
	SubFlag int64           `json:"subFlag"` // 驳回时用到，1：返回上级；2:流程结束
	Item    approveNodeItem `json:"item"`
}
type approveNodeItem struct {
	Id      int64  `json:"id"`
	Name    string `json:"name"`
	Reason  string `json:"reason"`
	Comment string `json:"comment"`
}

func approveTaskHandler(c *gin.Context) {
	var req approveParam
	var res common.Response

	if err := c.ShouldBindJSON(&req); err != nil {
		res.Format(c, err.Error())
		return
	}
	if req.TaskId == 0 || req.NodeId == 0 || req.Flag == 0 || req.SubFlag == 0 || req.Item.Id == 0 || (req.Item.Reason == "" && req.Item.Comment == "") {
		res.Format(c, "params error")
		return
	}

	var err error
	switch req.Flag {
	case 1: // 通过
		err = req.saveFlag1()
	case 2: // 驳回
		err = req.saveFlag2()
	case 3: // 批注
		err = req.saveFlag3(c)
	default:
		err = errors.New("不支持的审批类型")
	}
	if err != nil {
		res.Format(c, err.Error())
		return
	}

	res.Format(c)
}

// updateTaskHandler - 更新任务信息的处理器
func updateTaskHandler(c *gin.Context) {
	var res common.Response
	var req Task

	if err := c.ShouldBindJSON(&req); err != nil {
		res.Format(c, "参数解析失败: "+err.Error())
		return
	}

	// 验证必要参数
	if req.Id == 0 {
		res.Format(c, "任务ID不能为空")
		return
	}

	// 检查任务是否存在
	var existingTask Task
	has, err := common.DB.ID(req.Id).Get(&existingTask)
	if err != nil {
		res.Format(c, "查询任务失败: "+err.Error())
		return
	}
	if !has {
		res.Format(c, "任务不存在")
		return
	}

	// 只允许修改进行中状态的任务
	if existingTask.Status != 1 {
		res.Format(c, "只能修改进行中状态的任务")
		return
	}

	// 更新任务信息（只允许修改特定字段）
	updates := map[string]interface{}{
		"title":    req.Title,
		"content":  req.Content,
		"end_time": req.EndTime,
	}

	// 添加操作人信息
	updates["operator"] = c.GetString("username")
	updates["operator_name"] = c.GetString("realName")

	// 执行更新 - 使用原生SQL
	log.Printf("正在更新任务 %d，更新内容: %+v", req.Id, updates)

	sql := `UPDATE "task" SET "title" = ?, "content" = ?, "end_time" = ?, "operator" = ?, "operator_name" = ?, "update_time" = NOW() WHERE "id" = ?`
	result, err := common.DB.Exec(sql, req.Title, req.Content, req.EndTime, c.GetString("username"), c.GetString("realName"), req.Id)
	if err != nil {
		res.Format(c, "更新任务失败: "+err.Error())
		return
	}

	rowsAffected, _ := result.RowsAffected()
	log.Printf("更新结果: 影响行数 %d", rowsAffected)

	// 返回更新后的任务信息
	var updatedTask Task
	_, err = common.DB.ID(req.Id).Get(&updatedTask)
	if err != nil {
		res.Format(c, "获取更新后任务信息失败: "+err.Error())
		return
	}

	res.Data = updatedTask
	res.Format(c)
}

func getTaskTemplateNodeListHandler(c *gin.Context) {
	var res common.Response
	// 根据模板id，返回默认的工作流节点
	// 获取模板ID参数
	templateIdStr := c.Query("templateId")
	if templateIdStr == "" {
		res.Format(c, "templateId参数不能为空")
		return
	}
	templateId, err := strconv.ParseInt(templateIdStr, 10, 64)
	if err != nil {
		res.Format(c, "无效的模板ID")
		return
	}
	result, err := getTaskTemplateNodeList(templateId)
	if err != nil {
		res.Format(c, err.Error())
	}
	res.Data = result
	res.Format(c)
}

func getTaskNodeListHandler(c *gin.Context) {
	var res common.Response
	// 根据taskid，返回默认的工作流节点
	// 获取模板ID参数
	idStr := c.Query("id")
	if idStr == "" {
		res.Format(c, "id参数不能为空")
		return
	}
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		res.Format(c, "无效的模板ID")
		return
	}
	result, err := getTaskNodeList(id)
	if err != nil {
		res.Format(c, err.Error())
	}
	res.Data = result
	res.Format(c)
}

// TaskCenterRequest - task-center 接口请求参数
type TaskCenterRequest struct {
	Page     int64  `form:"page" json:"page"`         // 页码，从1开始
	PageSize int64  `form:"pageSize" json:"pageSize"` // 每页数量
	Status   int64  `form:"status" json:"status"`     // 任务状态筛选，可选：1=进行中，2=已结束，3=未完成
	Type     int64  `form:"type" json:"type"`         // 任务类型筛选，可选：1=公文，2=请假，3=提案
	Title    string `form:"title" json:"title"`       // 标题模糊搜索
}

// TaskCenterResponse - task-center 接口响应结构
type TaskCenterResponse struct {
	Total    int64   `json:"total"`    // 总记录数
	Page     int64   `json:"page"`     // 当前页码
	PageSize int64   `json:"pageSize"` // 每页数量
	List     []*Task `json:"list"`     // 任务列表
}

// taskCenterHandler - 获取 task 表数据的处理器
func taskCenterHandler(c *gin.Context) {
	var res common.Response
	var req TaskCenterRequest

	// 绑定查询参数
	if err := c.ShouldBindQuery(&req); err != nil {
		res.Format(c, "参数解析失败: "+err.Error())
		return
	}

	// 设置默认值
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}
	if req.PageSize > 100 {
		req.PageSize = 100 // 限制每页最大数量
	}

	// 计算分页偏移量
	offset := (req.Page - 1) * req.PageSize

	// 构建查询
	session := common.DB.NewSession().Table("task")

	// 添加筛选条件
	if req.Status > 0 {
		session = session.Where("status = ?", req.Status)
	}
	if req.Type > 0 {
		session = session.Where("type = ?", req.Type)
	}
	if req.Title != "" {
		session = session.Where("title LIKE ?", "%"+req.Title+"%")
	}

	// 获取总记录数
	total, err := session.Count()
	if err != nil {
		res.Format(c, "查询总记录数失败: "+err.Error())
		return
	}

	// 查询数据列表
	var tasks []*Task
	err = session.Asc("id").Limit(int(req.PageSize), int(offset)).Find(&tasks)
	if err != nil {
		res.Format(c, "查询任务列表失败: "+err.Error())
		return
	}

	// 构建响应
	response := TaskCenterResponse{
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
		List:     tasks,
	}

	res.Data = response
	res.Format(c)
}

// UploadTaskPdfRequest - 上传任务PDF请求
type UploadTaskPdfRequest struct {
	TaskId int64 `form:"taskId" json:"taskId" binding:"required"` // 任务ID
}

// uploadTaskPdfHandler - 上传任务PDF的处理函数
func uploadTaskPdfHandler(c *gin.Context) {
	var res common.Response

	// 获取任务ID
	taskIdStr := c.PostForm("taskId")
	if taskIdStr == "" {
		res.Format(c, "任务ID不能为空")
		return
	}

	taskId, err := strconv.ParseInt(taskIdStr, 10, 64)
	if err != nil {
		res.Format(c, "无效的任务ID")
		return
	}

	// 检查任务是否存在
	var existingTask Task
	has, err := common.DB.ID(taskId).Get(&existingTask)
	if err != nil {
		res.Format(c, "查询任务失败: "+err.Error())
		return
	}
	if !has {
		res.Format(c, "任务不存在")
		return
	}

	// 只允许上传进行中状态的任务的PDF
	if existingTask.Status != 1 {
		res.Format(c, "只能为进行中状态的任务上传PDF")
		return
	}

	// 获取上传的文件
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		res.Format(c, "获取文件失败: "+err.Error())
		return
	}
	defer file.Close()

	// 验证文件类型
	if header.Header.Get("Content-Type") != "application/pdf" {
		res.Format(c, "只能上传PDF文件")
		return
	}

	// 验证文件大小（限制为10MB）
	if header.Size > 10*1024*1024 {
		res.Format(c, "文件大小不能超过10MB")
		return
	}

	// 读取文件内容
	fileData := make([]byte, header.Size)
	_, err = file.Read(fileData)
	if err != nil {
		res.Format(c, "读取文件失败: "+err.Error())
		return
	}

	// 生成文件名：任务ID_时间戳_原文件名
	fileExt := filepath.Ext(header.Filename)
	objectName := fmt.Sprintf("task_%d_%d%s", taskId, time.Now().Unix(), fileExt)

	// 上传到officialDocument bucket
	s3Url, err := common.UploadOfficialDocument(objectName, fileData, "application/pdf")
	if err != nil {
		res.Format(c, "上传文件到S3失败: "+err.Error())
		return
	}

	// 更新任务的s3_url字段
	updates := map[string]interface{}{
		"s3_url":        s3Url,
		"operator":      c.GetString("username"),
		"operator_name": c.GetString("realName"),
	}

	_, err = common.DB.Table("task").Where("id = ?", taskId).Update(updates)
	if err != nil {
		res.Format(c, "更新任务S3 URL失败: "+err.Error())
		return
	}

	// 返回成功响应
	res.Data = map[string]interface{}{
		"taskId": taskId,
		"s3Url":  s3Url,
	}
	res.Format(c)
}

func RegisterRoutes(group *gin.RouterGroup) {
	group.POST("/task/newTask", newTaskHandler)
	group.POST("/task/approveTask", approveTaskHandler)
	group.GET("/task/getTemplateNodes", getTaskTemplateNodeListHandler)
	group.GET("/task/getTaskNodes", getTaskNodeListHandler)
	group.GET("/taskList", taskCenterHandler)
	group.POST("/task/updateTask", updateTaskHandler)
	group.POST("/task/uploadPdf", uploadTaskPdfHandler)
}
